package drds.plus.sql_process.optimizer.pusher;

import drds.plus.sql_process.abstract_syntax_tree.ObjectCreateFactory;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.JoinStrategy;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.column.Column;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.BooleanFilter;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Function;
import drds.plus.sql_process.abstract_syntax_tree.expression.order_by.OrderBy;
import drds.plus.sql_process.abstract_syntax_tree.node.Node;
import drds.plus.sql_process.abstract_syntax_tree.node.query.*;
import drds.plus.sql_process.optimizer.OptimizerContext;
import drds.plus.sql_process.optimizer.OptimizerException;
import drds.tools.$;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 将merge/join中的order by条件下推，包括隐式的order by条件，比如将groupBy转化为orderBy
 *
 * <pre>
 * a. 如果orderBy中包含function，也不做下推
 * b. 如果orderBy中的的column字段来自于子节点的函数查询，也不做下推
 * c. 如果join是SortMergeJoin，会下推join列
 *
 * 比如: tabl1.join(table2).on("table1.id=table2.id").addOrderByItemAndSetNeedBuild("id")
 * 转化为：where.addOrderByItemAndSetNeedBuild(id).join(table2).on("table1.id=table2.id")
 *
 * 下推例子：
 * 1.
 * 父节点：order by c1 ,c2 ,c3
 * 子节点: order by c1, c2
 * 优化：下推c3
 *
 * 2.
 * 父节点：order by c2 ,c3 (顺序不一致，强制下推)
 * 子节点: order by c2, c3，无limit
 * 优化：不下推
 *
 * 3.
 * 父节点：order by c2 ,c3 (顺序不一致，因为子节点存在limit，不可下推order by)
 * 子节点: order by c2,c3，存在limit
 * 优化：不下推
 *
 * 4.
 * 父节点：order by c1, c2 ,c3
 * 子节点: 无
 * 优化：下推c1,c2,c3
 *
 * 5.
 * 父节点：order by count(*) (函数不下推)
 * 子节点: 无
 * 优化：不下推
 */
public class OrderByPusher {

    /**
     * 详细优化见类描述 {@linkplain OrderByPusher}
     */
    public static Query optimize(Query query) {
        query = optimizeDistinct(query);
        query = pushOrderBy(query);
        return query;
    }

    /**
     * 处理Merge节点的distinct处理，需要底下节点先做排序
     *
     * <pre>
     * 排序优先级：
     * group by > order by > distinct
     * </pre>
     */
    private static Query optimizeDistinct(Query query) {
        for (Node node : query.getNodeList()) {
            if (node instanceof Query) {
                optimizeDistinct((Query) node);
            }
        }
        //
        if (query instanceof MergeQuery) {
            MergeQuery mergeQueryNode = (MergeQuery) query;
            if (!(mergeQueryNode.getFirstSubNodeQueryNode() instanceof Query)) {
                return mergeQueryNode;
            }
            if (containsDistinctColumns(mergeQueryNode)) {
                for (Node node : mergeQueryNode.getNodeList()) {
                    Query subQuery = (Query) node;
                    /**
                     * 重新构建order by / group by字段,原理是尽量order by满足group by,如果不满足则使用group by代替order by
                     */
                    if ($.isNotNullAndHasElement(subQuery.getGroupByList())) {
                        List<OrderBy> implicitOrderByList = subQuery.getCompleteOrderByList();
                        // 如果order by包含了所有的group by顺序
                        if (orderByListStartWithGroupByList(implicitOrderByList, subQuery.getGroupByList())) {
                            subQuery.setOrderByListAndSetNeedBuild(implicitOrderByList);
                        } else {
                            // order by不是一个group by的子集，优先使用group by
                            subQuery.setOrderByListAndSetNeedBuild(subQuery.getGroupByList());
                        }
                    }
                    /**
                     * distinct column without function
                     */
                    // 将查询所有字段进行order by，保证每个childNode返回的数据顺序都是一致的
                    List<OrderBy> selectItemThatIsNotFunctionOrderByList = new ArrayList<OrderBy>();
                    for (Item item : subQuery.getSelectItemList()) {
                        if (item instanceof Function) {// group by列已经包含了聚合函数需要的列
                            // count(distinct id)不列入distinct字段，因为已有distinct id的列
                            continue;
                        }
                        OrderBy orderBy = ObjectCreateFactory.createOrderBy();
                        orderBy.setColumn(item);
                        orderBy.setAsc(true);
                        selectItemThatIsNotFunctionOrderByList.add(orderBy);
                    }
                    boolean shardColumnAllIsGroupByColumn = mergeQueryNode.isDistinctShardColumns();
                    if ($.isNotNullAndHasElement(subQuery.getOrderByList())) {// 再判断一次分库分表键
                        // 判断一下是否为distinct分库键
                        if (shardColumnAllIsGroupByColumn(subQuery, selectItemThatIsNotFunctionOrderByList)) {
                            mergeQueryNode.setDistinctShardColumns(true);
                            shardColumnAllIsGroupByColumn = true;
                        }
                    }
                    /**
                     * column that is function
                     */
                    // 尝试去掉function函数，比如count(distinct id)
                    List<Function> functionList = new ArrayList();// 函数
                    for (Item item : subQuery.getSelectItemList()) {
                        if (item instanceof Function) {
                            functionList.add((Function) item);
                        }
                    }
                    if (shardColumnAllIsGroupByColumn) {//直接下发到某个数据节点
                        if ($.isNotNullAndHasElement(functionList)) { // 存在count(distinct id)函数
                            List<Item> distinctItemList = new ArrayList<Item>();
                            for (Item item : subQuery.getSelectItemList()) {
                                if (item instanceof Item && item.isDistinct()) {// distinct
                                    distinctItemList.add(item);
                                }
                            }
                            // 删除distinct id列
                            subQuery.getSelectItemList().removeAll(distinctItemList);// 子节点不能包含distinct列
                        } // 这样就可以下推了
                    } else {
                        subQuery.getSelectItemList().removeAll(functionList);
                        // 尝试调整下distinct的order by顺序，调整不了的话，按照distinct columns顺序
                        List<OrderBy> orderByList = toBePushedDownOrderByList(selectItemThatIsNotFunctionOrderByList, subQuery.getOrderByList());
                        if ($.isNotNullAndHasElement(orderByList)) {
                            subQuery.setOrderByListAndSetNeedBuild(orderByList);
                        } else {
                            subQuery.setOrderByListAndSetNeedBuild(selectItemThatIsNotFunctionOrderByList);
                        }
                    }
                    // 清空child的group by，由merge节点进行处理
                    subQuery.setGroupByListAndSetNeedBuild(new ArrayList(0));// 暂时不要分组了,order by 已经满足了,由上层处理就行了,下层处理浪费资源
                }

                if (!mergeQueryNode.isDistinctShardColumns()) {
                    // merge上的函数设置为distinct标记
                    for (Item item : mergeQueryNode.getSelectItemList()) {
                        if (item instanceof Function && isDistinct(item)) {
                            ((Function) item).setNeedDistinctArg(true);// 前面去掉了functionList,那么就需要父级的节点进行distinct处理
                        }
                    }
                }
                mergeQueryNode.build();
                return mergeQueryNode;
            }
        } else if (query instanceof Join || query instanceof $Query$) {
            if ($.isNotNullAndHasElement(query.getGroupByList())) {
                // 如果存在group by + distinct，暂时无法做优化
                return query;
            }
            if (containsDistinctColumns(query)) {
                // 将查询所有字段进行order by，保证每个child返回的数据顺序都是一致的
                List<OrderBy> distinctList = new ArrayList<OrderBy>();
                for (Item item : query.getSelectItemList()) {
                    OrderBy orderBy = ObjectCreateFactory.createOrderBy();
                    orderBy.setColumn(item);
                    orderBy.setAsc(true);
                    distinctList.add(orderBy);
                }
                List<OrderBy> orderByList = toBePushedDownOrderByList(distinctList, query.getOrderByList());// distinct列下推
                if ($.isNotNullAndHasElement(orderByList)) {
                    // 尝试合并order by和distinct成功，则设置当前order by
                    query.setOrderByListAndSetNeedBuild(orderByList);
                }
                query.build();
            }
        }

        return query;
    }

    private static Query pushOrderBy(Query query) {
        if (query instanceof MergeQuery) {
            MergeQuery mergeQueryNode = (MergeQuery) query;
            if (!(mergeQueryNode.getFirstSubNodeQueryNode() instanceof Query)) {
                return query;
            }
            if (mergeQueryNode.isUnion()) {// 只有order by 没有group by.如有自己管自己
                List<OrderBy> implicitOrderByList = ((Query) mergeQueryNode.getFirstSubNodeQueryNode()).getCompleteOrderByList();
                for (Node node : mergeQueryNode.getNodeList()) {
                    ((Query) node).setOrderByListAndSetNeedBuild(new ArrayList(0));
                    // 优先以主键为准
                    if (node instanceof TableQuery) {
                        if (((TableQuery) node).getIndexMappingUsed().isPrimaryKeyIndex()) {
                            implicitOrderByList = ((TableQuery) node).getCompleteOrderByList();
                        }
                    }
                }
                for (Node node : mergeQueryNode.getNodeList()) {
                    ((Query) node).setOrderByListAndSetNeedBuild(implicitOrderByList);
                    node.build();
                }
            } else {
                // 比如merge节点同时存在order by/group by
                // 1. 优先下推父节点的group by到子节点
                // 2. 然后去掉子节点的group by
                for (Node node : mergeQueryNode.getNodeList()) {
                    if (!(node instanceof Query)) {
                        continue;
                    }
                    Query subQuery = (Query) node;
                    if ($.isNotNullAndHasElement(subQuery.getGroupByList())) {
                        boolean isGroupByShardColumns = false;
                        if ((!$.isNotNullAndHasElement(subQuery.getOrderByList()))//
                                && shardColumnAllIsGroupByColumn(subQuery, subQuery.getGroupByList())) {
                            // 针对无order by,并且是groupBy分库键,打个标记
                            mergeQueryNode.setGroupByShardColumns(true);
                            isGroupByShardColumns = true;
                        } else {
                            // 如果非分库键的group, having在merge做，child清空having条件
                            subQuery.having("");
                        }
                        if (isGroupByShardColumns) {
                            // 跳过
                        } else {
                            // 需要考虑，如果子节点的列中存在聚合函数，则不能去除子节点的group by，否则语义不正确
                            // order by中可能有desc的倒排语法
                            // 目前的做法是设置orderby/groupby使用相同的列
                            List<OrderBy> implicitOrderByList = subQuery.getCompleteOrderByList();
                            // order by不是一个group by的子集，优先使用group by
                            if (orderByListStartWithGroupByList(implicitOrderByList, subQuery.getGroupByList())) {
                                subQuery.setOrderByListAndSetNeedBuild(implicitOrderByList);
                            } else {
                                subQuery.setOrderByListAndSetNeedBuild(subQuery.getGroupByList());
                            }
                        }
                        subQuery.build();
                    }
                }

                mergeQueryNode.build();
            }
        } else if (query instanceof Join) {
            // index nested loop中的order by，可以推到左节点
            Join joinNode = (Join) query;
            if (joinNode.getJoinStrategy() == JoinStrategy.index_nest_loop_join || joinNode.getJoinStrategy() == JoinStrategy.nest_loop_join) {
                // 左表排序隐式下推
                List<OrderBy> orderByList = toBePushedDownOrderByList(joinNode, joinNode.getLeftNode(), joinNode.getCompleteOrderByList(), true);
                pushJoinOrder(joinNode.getLeftNode(), orderByList, joinNode.isPrimaryKeyJoin());
            } else if (joinNode.getJoinStrategy() == JoinStrategy.sort_merge_join) {
                // 如果是SORT_MERGE_JOIN中的order by，需要推到左/右节点
                List<OrderBy> implicitOrderByList = joinNode.getCompleteOrderByList();
                Map<Item, OrderBy> itemToOrderByMap = new HashMap<Item, OrderBy>();
                for (OrderBy orderBy : implicitOrderByList) {
                    itemToOrderByMap.put(orderBy.getItem(), orderBy);
                }
                List<OrderBy> leftJoinOrderByList = new ArrayList<OrderBy>();
                List<OrderBy> rightJoinOrderByList = new ArrayList<OrderBy>();
                for (BooleanFilter joinFilter : joinNode.getJoinFilterList()) {
                    Item column = (Item) joinFilter.getColumn();
                    Item value = (Item) joinFilter.getValue();
                    if (!(column instanceof Column && value instanceof Column)) {
                        throw new OptimizerException("join列出现函数列,下推函数orderby过于复杂,此时sort sort join无法支持");
                    }
                    // 复制下隐藏order by的asc/desc
                    boolean asc = true;
                    OrderBy orderBy = itemToOrderByMap.get(column);
                    if (orderBy != null) {
                        asc = orderBy.getAsc();
                    }
                    orderBy = itemToOrderByMap.get(value);
                    if (orderBy != null) {
                        asc = orderBy.getAsc();
                    }
                    OrderBy leftOrderBy = ObjectCreateFactory.createOrderBy();
                    leftOrderBy.setColumn(column);
                    leftOrderBy.setAsc(asc);
                    leftJoinOrderByList.add(leftOrderBy);
                    OrderBy rightOrderBy = ObjectCreateFactory.createOrderBy();
                    rightOrderBy.setColumn(value);
                    rightOrderBy.setAsc(asc);
                    rightJoinOrderByList.add(rightOrderBy);
                }
                // 调整下join orderBys的顺序，尽可能和原始的order by顺序一致，这样可以有利于下推
                adjustJoinImplicitOrderByList(implicitOrderByList, leftJoinOrderByList, rightJoinOrderByList);
                // 先推join列，如果join列推失败了，比如join列是函数列，这问题就蛋疼了，需要提前做判断
                List<OrderBy> leftSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getLeftNode(), leftJoinOrderByList, true);
                pushJoinOrder(joinNode.getLeftNode(), leftSideOrderByList, joinNode.isPrimaryKeyJoin());

                List<OrderBy> rightSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getRightNode(), rightJoinOrderByList, true);
                pushJoinOrder(joinNode.getRightNode(), rightSideOrderByList, joinNode.isPrimaryKeyJoin());
                //
                if ($.isNotNullAndHasElement(implicitOrderByList)) {
                    // group by + order by的隐藏列，如果和join列前缀相同，则下推，否则忽略
                    // 已经推了一次join column，这里不能再强推了
                    leftSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getLeftNode(), implicitOrderByList, false);
                    rightSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getRightNode(), implicitOrderByList, false);
                    if (!leftSideOrderByList.isEmpty() || !rightSideOrderByList.isEmpty()) {
                        pushJoinOrder(joinNode.getLeftNode(), leftSideOrderByList, joinNode.isPrimaryKeyJoin());
                        pushJoinOrder(joinNode.getRightNode(), rightSideOrderByList, joinNode.isPrimaryKeyJoin());
                    } else {
                        // 尝试一下只推group by的排序，减少一层排序
                        if ($.isNotNullAndHasElement(joinNode.getGroupByList())) {
                            List<OrderBy> leftSideOrderByListForGroupByList = toBePushedDownOrderByList(joinNode.getGroupByList(), leftJoinOrderByList);
                            List<OrderBy> rightSideOrderByListForGroupByList = toBePushedDownOrderByList(joinNode.getGroupByList(), rightJoinOrderByList);
                            // 重置下group by的顺序
                            if (!leftSideOrderByListForGroupByList.isEmpty()) {
                                joinNode.setGroupByListAndSetNeedBuild(leftSideOrderByListForGroupByList);
                            } else if (!rightSideOrderByListForGroupByList.isEmpty()) {
                                joinNode.setGroupByListAndSetNeedBuild(rightSideOrderByListForGroupByList);
                            }

                            leftSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getLeftNode(), leftSideOrderByListForGroupByList, false);
                            rightSideOrderByList = toBePushedDownOrderByList(joinNode, joinNode.getRightNode(), rightSideOrderByListForGroupByList, false);
                            if (!leftSideOrderByList.isEmpty() || !rightSideOrderByList.isEmpty()) {
                                pushJoinOrder(joinNode.getLeftNode(), leftSideOrderByList, joinNode.isPrimaryKeyJoin());
                                pushJoinOrder(joinNode.getRightNode(), rightSideOrderByList, joinNode.isPrimaryKeyJoin());
                            }
                        }
                    }
                }
            }

            joinNode.build();
        } else if (query instanceof $Query$) {
            // 可以将order推到子查询
            $Query$ $Query$Node = ($Query$) query;
            List<OrderBy> orderByList = toBePushedDownOrderByList($Query$Node, $Query$Node.getFirstSubNodeQueryNode(), $Query$Node.getCompleteOrderByList(), true);
            if (orderByList != null && !orderByList.isEmpty()) {
                for (OrderBy orderBy : orderByList) {
                    $Query$Node.getFirstSubNodeQueryNode().addOrderByItemAndSetNeedBuild(orderBy.getItem(), orderBy.getAsc());
                }
            }
            $Query$Node.build();
        }
        for (Node node : query.getNodeList()) {
            if (node instanceof Query) {
                pushOrderBy((Query) node);
            }
        }

        return query;
    }

    /**
     * 判断是否存在distinct函数
     */
    private static boolean containsDistinctColumns(Query query) {
        for (Item item : query.getSelectItemList()) {
            if (isDistinct(item)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isDistinct(Item item) {
        if (item.isDistinct()) {
            return true;
        }

        if (item instanceof Function) {
            for (Object arg : ((Function) item).getArgList()) {
                if (arg instanceof Item) {
                    if (isDistinct((Item) arg)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * order by list的开头几项在列字段和顺序都一致(by czh),但group by是一个整体,可以交换顺序来满足order by。
     *
     * <pre>
     * 下面的注释和该方法没有必然关系 ,它是order by和group by之间是否可以优化的判断依据。
     * 针对order by id,columnName group by id
     * 子节点先按照id做group by,因为子节点的order by和父节点的group by满足一个前序匹配，这里直接使用父节点id,Name做order by
     * merge节点先按id做group by(底下子节点为id,name排序，不需要临时表排序)，groupby处理后的结果也满足id,name的排序，直接返回，不需要临时表
     * --存在交集
     * 比如：order by id,columnName group by id , 合并的结果为order by id,columnName 和 group by id是一个前序匹配
     * 比如：order by id,group by columnName id , 合并的结果为order by id,columnName，和 group by id,name是一个前序匹配
     * --不存在交集
     * 比如：order by columnName,id group by id , 合并的结果为order by columnName,id，和group by id不是一个前序匹配
     * 比如：order by id,group by columnName,school , 合并的结果为order by id，和group by columnName,school不是一个前序匹配
     * </pre>
     */
    private static boolean orderByListStartWithGroupByList(List<OrderBy> orderByList, List<OrderBy> groupByList) {
        if (groupByList.size() > orderByList.size()) {
            return false;
        }
        int i = 0;
        for (OrderBy group : groupByList) {
            boolean found = false;
            int j = 0;
            for (OrderBy orderBy : orderByList) {
                if (orderBy.getItem().equals(group.getItem())) {
                    found = true;
                    break;
                }
                j++;
            }
            if (!found || i != j) {
                // 没找到或者顺序不匹配
                return false;
            }
            i++;
        }
        return true;
    }

    /**
     * 调整join列，按照order by的顺序，有利于下推
     */
    private static void adjustJoinImplicitOrderByList(List<OrderBy> implicitOrderByList, List<OrderBy> leftJoinOrderByList, List<OrderBy> rightJoinOrderByList) {
        // 调整下join order by的顺序，尽可能和原始的order by顺序一致，这样可以有利于下推
        for (int i = 0; i < implicitOrderByList.size(); i++) {
            if (i >= leftJoinOrderByList.size()) {
                return;
            }
            OrderBy orderBy = implicitOrderByList.get(i);
            int leftIndex = getIndexInOrderByList(leftJoinOrderByList, orderBy.getItem());
            int rightIndex = getIndexInOrderByList(rightJoinOrderByList, orderBy.getItem());

            int index = -1;
            if (leftIndex >= 0 && leftIndex != i) { // 判断位置是否相同
                index = leftIndex;
            } else if (rightIndex >= 0 && rightIndex != i) {
                index = rightIndex;
            }

            if (index >= 0) {
                // 交换位置一下
                OrderBy tempOrderBy = leftJoinOrderByList.get(i);
                leftJoinOrderByList.set(i, leftJoinOrderByList.get(index));
                leftJoinOrderByList.set(index, tempOrderBy);

                tempOrderBy = rightJoinOrderByList.get(i);
                rightJoinOrderByList.set(i, rightJoinOrderByList.get(index));
                rightJoinOrderByList.set(index, tempOrderBy);
            } else {
                return;// join列中没有order by的字段，直接退出
            }
        }
    }

    /**
     * 尝试对比父节点中的order by和子节点的order by顺序，如果前缀一致，则找出末尾的order by字段进行返回
     *
     * <pre>
     * 比如
     * 1.
     *  父节点：order by c1 ,c2 ,c3
     *  子节点: order by c1, c2
     *
     * 返回为c3
     *
     * 2.
     *  父节点：order by c2 ,c3
     *  子节点: order by c1, c2，不存在limit
     *
     * 返回为c2,c3
     *
     * 3.
     *  父节点：order by c2 ,c3
     *  子节点: order by c1, c2，存在limit
     *
     * 返回为空
     *
     * 4.
     *  父节点：order by c1, c2 ,c3
     *  子节点: 无
     *
     * 返回为c1,c2,c3
     *
     * 5.
     *  父节点：order by count(*)  (函数不下推)
     *  子节点: 无
     *
     * 返回空
     * </pre>
     */
    private static List<OrderBy> toBePushedDownOrderByList(Query query, Query subNodeQuery, List<OrderBy> implicitOrderByList, boolean forcePush) {
        List<OrderBy> orderByList = new ArrayList<OrderBy>();
        List<OrderBy> subNodeQueryNodeOrderByList = subNodeQuery.getOrderByList();
        if (implicitOrderByList == null || implicitOrderByList.size() == 0) {
            return new ArrayList<OrderBy>();
        }
        for (int i = 0; i < implicitOrderByList.size(); i++) {
            OrderBy orderBy = implicitOrderByList.get(i);
            Item item = query.getItem(orderBy.getItem());// 找到select或者是meta中的字段
            if (!(item != null && item instanceof Column)) {
                // 可能order by的字段为当前select的函数列
                return new ArrayList<OrderBy>();
            }

            // 在子节点中找一次，转化为子节点中的字段信息，比如表名，这样才可以和orderby字段做比较
            item = subNodeQuery.getItem(item);
            if (!(item != null && item instanceof Column)) {
                // 可能order by的字段为当前select的函数列
                return new ArrayList<OrderBy>();
            }

            forcePush &= (subNodeQuery.getLimitFrom() == null && subNodeQuery.getLimitTo() == null);
            if (!forcePush) {
                // 如果非强制下推，判断一下order by顺序
                if (subNodeQueryNodeOrderByList != null && subNodeQueryNodeOrderByList.size() > i) {
                    OrderBy subNodeQueryNodeOrderBy = subNodeQueryNodeOrderByList.get(i);
                    if (!(item.equals(subNodeQueryNodeOrderBy.getItem()) && orderBy.getAsc().equals(subNodeQueryNodeOrderBy.getAsc()))) {
                        // 如果不相同
                        return new ArrayList<OrderBy>();
                    }
                } else {
                    // 如果出现父类的长度>子类
                    Item copy = item.copy();
                    copy.setAlias(null);
                    OrderBy newOrder = orderBy.copy();
                    newOrder.setColumn(copy);
                    orderByList.add(newOrder);
                }
            } else {
                // 直接复制
                Item copy = item.copy();
                copy.setAlias(null);
                OrderBy newOrderBy = orderBy.copy();
                newOrderBy.setColumn(copy);
                orderByList.add(newOrderBy);
            }
        }
        if (!orderByList.isEmpty() && forcePush) {
            // 干掉子节点原本的order by
            subNodeQuery.setOrderByListAndSetNeedBuild(new ArrayList<OrderBy>());
        }
        return orderByList;
    }

    /**
     * 如果可以下推返回返回下推后的,否则返回空list
     *
     * @param toBePushedDownOrderByList 待进行下推处理的
     * @param basicOrderByList          以这个为基准,必须包含这个
     */
    private static List<OrderBy> toBePushedDownOrderByList(List<OrderBy> toBePushedDownOrderByList, List<OrderBy> basicOrderByList) {
        List<OrderBy> orderByList = new ArrayList<OrderBy>();
        for (OrderBy orderBy : basicOrderByList) {
            if (getIndexInOrderByList(toBePushedDownOrderByList, orderBy.getItem()) >= 0) {
                orderByList.add(orderBy);// 标准列放前面,同时保证order by原有列的顺序
            } else {
                return new ArrayList<OrderBy>();// 不能下推 // 返回一般的顺序没用
            }
        }

        for (OrderBy orderBy : toBePushedDownOrderByList) {
            // 找到join column中没有的进行添加
            if (getIndexInOrderByList(orderByList, orderBy.getItem()) < 0) {
                orderByList.add(orderBy);// 非标准列放后面
            }
        }

        return orderByList;
    }

    /**
     * 尝试查找一个同名的排序字段，返回下标，-1代表没找到
     */
    private static int getIndexInOrderByList(List<OrderBy> orderByList, Item item) {
        for (int i = 0; i < orderByList.size(); i++) {
            OrderBy orderBy = orderByList.get(i);
            if (orderBy.getItem().equals(item)) {
                return i;
            }
        }

        return -1;
    }

    private static void pushJoinOrder(Query query, List<OrderBy> orderByList, boolean primaryKeyJoin) {
        if (orderByList != null && !orderByList.isEmpty()) {
            for (OrderBy orderBy : orderByList) {
                if (query.hasItem(orderBy.getItem())) {
                    query.addOrderByItemAndSetNeedBuild(orderBy.getItem(), orderBy.getAsc());
                } else if (primaryKeyJoin) {
                    // 尝试忽略下表名查找一下
                    Item item = orderBy.getItem().copy();
                    item.setTableName(null);
                    if (query.hasItem(item)) {
                        query.addOrderByItemAndSetNeedBuild(orderBy.getItem(), orderBy.getAsc());
                    }
                }
            }

            query.build();
        }
    }

    /**
     * 检查下group列是否为分库键列，无顺序要求
     */
    private static boolean shardColumnAllIsGroupByColumn(Query query, List<OrderBy> groupByList) {
        if (!(query instanceof TableQuery)) {
            return false;
        }
        // 后续可考虑下join sort join，join存在groupBy为单库的分库键
        TableQuery tableQueryNode = (TableQuery) query;
        List<String> shardColumnNameList = OptimizerContext.getOptimizerContext().getRouteOptimizer().getShardColumnNameList(tableQueryNode.getTableName());
        List<OrderBy> newGroupByList = new ArrayList<OrderBy>();
        for (String shardColumnName : shardColumnNameList) {
            boolean isFound = false;
            for (OrderBy groupBy : groupByList) {
                if (groupBy.getItem() instanceof Function) {
                    return false;
                } else if (groupBy.getItem().getColumnName().equals(shardColumnName)) {
                    // groupBy的列来自于select或者tableMeta，只比较列名，不比较别名
                    isFound = true;
                    newGroupByList.add(groupBy);
                    break;
                }
            }
            if (!isFound) {
                // 找不到分库键
                return false;
            }
        }
        // 所有都找到
        return true;
    }
}
